package com.jh.concurrent.threadpool;

import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author JH_Wong
 * @projectName newforward
 * @title ThreadPoolMonitor.java
 * @package com.jh.concurrent.threadpool
 * @description 线程池监视器
 * @date 2019-05-28 09:35
 */
public class ThreadPoolMonitor extends ThreadPoolExecutor {

    private ConcurrentHashMap<String, Date> runTimes;

    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        runTimes = new ConcurrentHashMap<>();
    }

    @Override
    public void shutdown() {

        System.out.println("---------------- shutdown ----------------------");
        System.out.println("已执行任务数：" + this.getCompletedTaskCount() + "\n"
                + "当前活动线程数：" + this.getActiveCount() + "\n"
                + "当前排队线程数：" + this.getQueue().size());

        super.shutdown();
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        runTimes.put(String.valueOf(r.hashCode()), new Date());
        super.beforeExecute(t, r);
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        Date startDate = runTimes.remove(String.valueOf(r.hashCode()));
        Date endDate = new Date();
        long diff = endDate.getTime() - startDate.getTime();

        System.out.println("--------------- afterExecute ----------------");
        System.out.println("任务耗时：" + diff + "\n"
                + "初始线程数：" + this.getPoolSize() + "\n"
                + "核心线程数：" + this.getCorePoolSize() + "\n"
                + "正在执行任务数：" + this.getActiveCount() + "\n"
                + "已执行任务数：" + this.getCompletedTaskCount() + "\n"
                + "任务总数：" + this.getTaskCount() + "\n"
                + "最大允许线程数：" + this.getMaximumPoolSize() + "\n"
                + "线程空闲时间：" + this.getKeepAliveTime(TimeUnit.SECONDS));

        super.afterExecute(r, t);
    }

    public static void main(String[] args) {
        ThreadPoolMonitor monitor = new ThreadPoolMonitor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());

        for (int i = 0; i < 10; i++) {
            monitor.execute(new TestThread());
        }

        monitor.shutdown();
    }

    private final static class TestThread implements Runnable {

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
